package com.pay;

import com.exception.ApiException;
import com.util.JsonUtil;
import com.util.MyUUID;
import com.util.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.TreeMap;

/**
 * @author: cxt
 * @time: 2022/5/17
 */
@Slf4j
public class ConlinPayUtil {

    private static final String APPID = "20170309130500000023";

    private static final String KEY = "Ahds765uwWUNU0292KKW==";

    private static final String URL = "http://test.conlin360.net:15656/api/v1/";

    /**
     * 秘钥拼接签名，发送请求
     *
     * @param map 请求的参数
     * @return 请求结果
     */
    public static TreeMap<String, Object> splicingByMD5(TreeMap<String, Object> map) {
        map.put("AppId", APPID);
        map.put("Class", "27"); // 费用分类
        map.put("Channel", "29"); // 请求渠道
        String random = MyUUID.createStrId();
        map.put("Random", random);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:ss:mm");
        String format = LocalDateTime.now().format(formatter);
        map.put("ReqTime", format);

        StringBuilder builder = new StringBuilder();
        map.forEach((k, v) -> {
            builder.append(k).append("=").append(v).append("&");
        });
        builder.append("key=").append(KEY);

        String sign = SecureUtil.hashByMD5(builder.toString());
        map.put("Sign", sign);

        Object parameter = map.get("Args");
        TreeMap treeMap = JsonUtil.getPerson((String) parameter, TreeMap.class);
        map.put("Args", treeMap);

        return reqInterface(map);
    }

    /**
     * 请求接口
     *
     * @return 请求结果
     */
    public static TreeMap<String, Object> reqInterface(TreeMap<String, Object> map) {
        MediaType type = MediaType.parseMediaType("application/json");
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(type);
        try {
//            RestTemplate restTemplate = SpringBeanHelper.getBean(RestTemplate.class);
            RestTemplate restTemplate = new RestTemplate();
            String kind = (String) map.get("Kind");
            String url = URL + kind.toLowerCase();
            log.info("发送[{}]请求：{}", map.get("Kind"), map);
            TreeMap result = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(map, headers), TreeMap.class).getBody();
            if (result != null) {
                if (verification(result)) {
                    log.info("请求结果：{}", result);
                    return result;
                } else {
                    log.error("请求失败：{}", result);
                    throw new ApiException("系统异常，签名验证失败");
                }
            } else {
                throw new ApiException("系统异常,支付调用返回结果为空");
            }
        } catch (HttpClientErrorException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 验签
     *
     * @param map 返回数据
     * @return 验证结果
     */
    public static boolean verification(TreeMap<String, Object> map) {
        boolean result = false;
        String signOld = (String) map.get("Sign");
        map.remove("Sign");
        LinkedHashMap<String, String> args = (LinkedHashMap<String, String>) map.get("Args");
        TreeMap<String, String> treeMap = new TreeMap<>();
        args.forEach((k, v) -> {
            if (v != null) {
                treeMap.put(k, v);
            }
        });

        String json = JsonUtil.createJson(treeMap);
        map.put("Args", json);
        StringBuilder builder = new StringBuilder();
        map.forEach((k, v) -> {
            builder.append(k).append("=").append(v).append("&");
        });
        builder.append("key=").append(KEY);

        String signNew = SecureUtil.hashByMD5(builder.toString());

        if (signOld.equals(signNew)) {
            result = true;
        }

        return result;
    }
}
